package com.itheima.ai.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.itheima.ai.config.ZhipuConfig;
import com.itheima.ai.repository.ChatMessageRepository;
import com.itheima.ai.repository.ChatSessionRepository;
import com.itheima.ai.service.ChatService;
import com.itheima.model.ai.dtos.ChatRequest;
import com.itheima.model.ai.dtos.ChatResponse;
import com.itheima.model.ai.pojos.ChatMessage;
import com.itheima.model.ai.pojos.ChatSession;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Flux;

import java.nio.charset.StandardCharsets;
import java.util.*;

@Slf4j
@Service
public class ChatServiceImpl implements ChatService {
    
    @Autowired
    private WebClient zhipuWebClient;
    
    @Autowired
    private ZhipuConfig zhipuConfig;
    
    @Autowired
    private ChatMessageRepository messageRepository;
    
    @Autowired
    private ChatSessionRepository sessionRepository;
    
    @Override
    @Transactional
    public ChatResponse sendMessage(ChatRequest request) {
        log.info("收到聊天请求: userId={}, sessionId={}, message={}", 
                request.getUserId(), request.getSessionId(), request.getMessage());
        
        // 1. 获取或创建会话
        ChatSession session = getOrCreateSession(request.getUserId(), request.getSessionId());
        
        // 2. 保存用户消息
        ChatMessage userMessage = new ChatMessage();
        userMessage.setUserId(request.getUserId());
        userMessage.setSessionId(session.getId());
        userMessage.setRole("user");
        userMessage.setContent(request.getMessage());
        userMessage.setCreateTime(new Date());
        userMessage.setModel(zhipuConfig.getModel());
        messageRepository.save(userMessage);
        
        // 3. 构建上下文消息列表（最近10条）
        List<ChatMessage> historyMessages = messageRepository
                .findBySessionIdOrderByCreateTimeAsc(session.getId());
        
        // 只取最近的10条消息作为上下文
        int contextSize = Math.min(10, historyMessages.size());
        List<ChatMessage> contextMessages = historyMessages.subList(
                Math.max(0, historyMessages.size() - contextSize), 
                historyMessages.size()
        );
        
        List<ChatMessage> messages = new ArrayList<>();
        
        // 添加系统提示词
        ChatMessage systemMessage = new ChatMessage();
        systemMessage.setRole("system");
        systemMessage.setContent("你是一个智能阅读助手，可以帮助用户分析、总结和理解阅读内容。请用简洁、专业的语言回答问题。");
        messages.add(systemMessage);
        
        // 添加上下文消息
        messages.addAll(contextMessages);
        
        // 4. 调用智谱AI
        try {
            String aiReply = callZhipuAI(messages);
            
            // 5. 保存AI回复
            ChatMessage assistantMessage = new ChatMessage();
            assistantMessage.setUserId(request.getUserId());
            assistantMessage.setSessionId(session.getId());
            assistantMessage.setRole("assistant");
            assistantMessage.setContent(aiReply);
            assistantMessage.setCreateTime(new Date());
            assistantMessage.setModel(zhipuConfig.getModel());
            ChatMessage savedMessage = messageRepository.save(assistantMessage);
            
            // 6. 更新会话
            session.setUpdateTime(new Date());
            session.setMessageCount(session.getMessageCount() + 2); // 用户消息 + AI回复
            sessionRepository.save(session);
            
            // 7. 构造返回结果
            ChatResponse response = new ChatResponse();
            response.setSessionId(session.getId());
            response.setReply(aiReply);
            response.setMessageId(savedMessage.getId());
            response.setModel(zhipuConfig.getModel());
            
            log.info("AI回复成功: sessionId={}, messageId={}", session.getId(), savedMessage.getId());
            return response;
            
        } catch (Exception e) {
            log.error("调用智谱AI失败", e);
            throw new RuntimeException("AI服务暂时不可用，请稍后重试");
        }
    }
    
    @Override
    public Flux<String> sendMessageStream(ChatRequest request) {
        log.info("收到流式聊天请求: userId={}, sessionId={}, message={}", 
                request.getUserId(), request.getSessionId(), request.getMessage());
        
        // 1. 获取或创建会话
        ChatSession session = getOrCreateSession(request.getUserId(), request.getSessionId());
        
        // 2. 保存用户消息
        ChatMessage userMessage = new ChatMessage();
        userMessage.setUserId(request.getUserId());
        userMessage.setSessionId(session.getId());
        userMessage.setRole("user");
        userMessage.setContent(request.getMessage());
        userMessage.setCreateTime(new Date());
        userMessage.setModel(zhipuConfig.getModel());
        messageRepository.save(userMessage);
        
        // 3. 获取历史消息
        List<ChatMessage> historyMessages = messageRepository
                .findBySessionIdOrderByCreateTimeAsc(session.getId());
        
        int contextSize = Math.min(10, historyMessages.size());
        List<ChatMessage> contextMessages = historyMessages.subList(
                Math.max(0, historyMessages.size() - contextSize), 
                historyMessages.size()
        );
        
        List<ChatMessage> messages = new ArrayList<>();
        ChatMessage systemMessage = new ChatMessage();
        systemMessage.setRole("system");
        systemMessage.setContent("你是一个智能阅读助手，可以帮助用户分析、总结和理解阅读内容。请用简洁、专业的语言回答问题。");
        messages.add(systemMessage);
        messages.addAll(contextMessages);
        
        // 构建请求体
        JSONObject requestBody = new JSONObject();
        requestBody.put("model", zhipuConfig.getModel());
        requestBody.put("temperature", zhipuConfig.getTemperature());
        requestBody.put("max_tokens", zhipuConfig.getMaxTokens());
        requestBody.put("stream", true);
        
        JSONArray messagesArray = new JSONArray();
        for (ChatMessage msg : messages) {
            JSONObject msgObj = new JSONObject();
            msgObj.put("role", msg.getRole());
            msgObj.put("content", msg.getContent());
            messagesArray.add(msgObj);
        }
        requestBody.put("messages", messagesArray);
        
        log.info("调用智谱AI流式接口: model={}, messageCount={}", zhipuConfig.getModel(), messages.size());
        
        // 用于累积完整回复以保存到数据库
        final StringBuilder fullReply = new StringBuilder();
        final StringBuilder lineBuffer = new StringBuilder();
        
        // 4. 返回流式响应
        return Flux.concat(
            // 首先发送会话ID
            Flux.just("{\"type\":\"session\",\"sessionId\":\"" + session.getId() + "\"}\n"),
            
            // 然后处理AI的流式响应
            zhipuWebClient
                    .post()
                    .uri("/chat/completions")
                    .bodyValue(requestBody.toJSONString())
                    .retrieve()
                    .bodyToFlux(DataBuffer.class)
                    .concatMap(dataBuffer -> {
                        try {
                            byte[] bytes = new byte[dataBuffer.readableByteCount()];
                            dataBuffer.read(bytes);
                            String chunk = new String(bytes, StandardCharsets.UTF_8);
                            
                            lineBuffer.append(chunk);
                            String[] lines = lineBuffer.toString().split("\n");
                            
                            if (!lineBuffer.toString().endsWith("\n")) {
                                lineBuffer.setLength(0);
                                lineBuffer.append(lines[lines.length - 1]);
                                lines = Arrays.copyOf(lines, lines.length - 1);
                            } else {
                                lineBuffer.setLength(0);
                            }
                            
                            List<String> results = new ArrayList<>();
                            for (String line : lines) {
                                line = line.trim();
                                if (line.isEmpty()) continue;
                                
                                if (line.startsWith("data:")) {
                                    String data = line.substring(5).trim();
                                    if ("[DONE]".equals(data)) continue;
                                    
                                    try {
                                        JSONObject json = JSON.parseObject(data);
                                        JSONArray choices = json.getJSONArray("choices");
                                        if (choices != null && !choices.isEmpty()) {
                                            JSONObject choice = choices.getJSONObject(0);
                                            JSONObject delta = choice.getJSONObject("delta");
                                            if (delta != null) {
                                                String content = delta.getString("content");
                                                if (content != null && !content.isEmpty()) {
                                                    fullReply.append(content);
                                                    results.add("{\"type\":\"content\",\"content\":\"" + 
                                                        escapeJson(content) + "\"}\n");
                                                }
                                            }
                                        }
                                    } catch (Exception e) {
                                        log.error("解析JSON失败: {}", data, e);
                                    }
                                }
                            }
                            return Flux.fromIterable(results);
                        } finally {
                            DataBufferUtils.release(dataBuffer);
                        }
                    })
                    .doOnComplete(() -> {
                        // 保存完整回复
                        ChatMessage assistantMessage = new ChatMessage();
                        assistantMessage.setUserId(request.getUserId());
                        assistantMessage.setSessionId(session.getId());
                        assistantMessage.setRole("assistant");
                        assistantMessage.setContent(fullReply.toString());
                        assistantMessage.setCreateTime(new Date());
                        assistantMessage.setModel(zhipuConfig.getModel());
                        messageRepository.save(assistantMessage);
                        
                        // 更新会话
                        session.setUpdateTime(new Date());
                        session.setMessageCount(session.getMessageCount() + 2);
                        sessionRepository.save(session);
                        
                        log.info("流式聊天完成: sessionId={}, replyLength={}", session.getId(), fullReply.length());
                    }),
            
            // 最后发送完成信号
            Flux.just("{\"type\":\"done\"}\n")
        ).onErrorResume(e -> {
            log.error("流式聊天失败", e);
            return Flux.just("{\"type\":\"error\",\"message\":\"" + escapeJson(e.getMessage()) + "\"}\n");
        });
    }
    
    private String escapeJson(String str) {
        if (str == null) return "";
        return str.replace("\\", "\\\\")
                  .replace("\"", "\\\"")
                  .replace("\n", "\\n")
                  .replace("\r", "\\r")
                  .replace("\t", "\\t");
    }
    
    private String callZhipuAI(List<ChatMessage> messages) {
        try {
            // 构建请求体
            JSONObject requestBody = new JSONObject();
            requestBody.put("model", zhipuConfig.getModel());
            requestBody.put("temperature", zhipuConfig.getTemperature());
            requestBody.put("max_tokens", zhipuConfig.getMaxTokens());
            requestBody.put("stream", false);
            
            // 转换消息格式
            JSONArray messagesArray = new JSONArray();
            for (ChatMessage msg : messages) {
                JSONObject msgObj = new JSONObject();
                msgObj.put("role", msg.getRole());
                msgObj.put("content", msg.getContent());
                messagesArray.add(msgObj);
            }
            requestBody.put("messages", messagesArray);
            
            log.info("调用智谱AI: model={}, messageCount={}", zhipuConfig.getModel(), messages.size());
            log.debug("请求体: {}", requestBody.toJSONString());
            
            // 调用API
            String responseBody = zhipuWebClient
                    .post()
                    .uri("/chat/completions")
                    .bodyValue(requestBody.toJSONString())
                    .retrieve()
                    .bodyToMono(String.class)
                    .block();
            
            log.debug("响应体: {}", responseBody);
            
            // 解析响应
            JSONObject responseJson = JSON.parseObject(responseBody);
            
            // 检查错误
            if (responseJson.containsKey("error")) {
                JSONObject error = responseJson.getJSONObject("error");
                String errorMsg = error.getString("message");
                log.error("AI API错误: {}", errorMsg);
                throw new RuntimeException("AI服务错误: " + errorMsg);
            }
            
            // 提取回复内容
            JSONArray choices = responseJson.getJSONArray("choices");
            if (choices != null && !choices.isEmpty()) {
                JSONObject firstChoice = choices.getJSONObject(0);
                JSONObject message = firstChoice.getJSONObject("message");
                String content = message.getString("content");
                
                // 获取token使用情况
                if (responseJson.containsKey("usage")) {
                    JSONObject usage = responseJson.getJSONObject("usage");
                    log.info("AI回复成功，长度: {}, tokens: {}", 
                        content.length(), usage.getInteger("total_tokens"));
                }
                
                return content;
            }
            
            throw new RuntimeException("AI回复为空");
            
        } catch (Exception e) {
            log.error("调用智谱AI失败: {}", e.getMessage(), e);
            throw new RuntimeException("调用AI服务失败: " + e.getMessage(), e);
        }
    }
    
    private void callZhipuAIStream(List<ChatMessage> messages, java.util.function.Consumer<String> onContent) {
        try {
            // 构建请求体
            JSONObject requestBody = new JSONObject();
            requestBody.put("model", zhipuConfig.getModel());
            requestBody.put("temperature", zhipuConfig.getTemperature());
            requestBody.put("max_tokens", zhipuConfig.getMaxTokens());
            requestBody.put("stream", true);  // 启用流式
            
            // 转换消息格式
            JSONArray messagesArray = new JSONArray();
            for (ChatMessage msg : messages) {
                JSONObject msgObj = new JSONObject();
                msgObj.put("role", msg.getRole());
                msgObj.put("content", msg.getContent());
                messagesArray.add(msgObj);
            }
            requestBody.put("messages", messagesArray);
            
            log.info("调用智谱AI流式接口: model={}, messageCount={}", zhipuConfig.getModel(), messages.size());
            log.info("请求体: {}", requestBody.toJSONString());
            
            // 用于累积不完整的行
            final StringBuilder lineBuffer = new StringBuilder();
            final int[] contentCount = {0};
            
            // 调用流式API - 使用DataBuffer处理字节流
            zhipuWebClient
                    .post()
                    .uri("/chat/completions")
                    .bodyValue(requestBody.toJSONString())
                    .retrieve()
                    .bodyToFlux(DataBuffer.class)
                    .doOnNext(dataBuffer -> {
                        try {
                            // 将DataBuffer转为字符串
                            byte[] bytes = new byte[dataBuffer.readableByteCount()];
                            dataBuffer.read(bytes);
                            String chunk = new String(bytes, StandardCharsets.UTF_8);
                            
                            log.info("收到数据块，大小: {} 字节", chunk.length());
                            
                            // 将chunk添加到缓冲区
                            lineBuffer.append(chunk);
                            
                            // 按行处理
                            String[] lines = lineBuffer.toString().split("\n");
                            
                            // 如果最后不是换行符，保留最后一行（可能不完整）
                            if (!lineBuffer.toString().endsWith("\n")) {
                                lineBuffer.setLength(0);
                                lineBuffer.append(lines[lines.length - 1]);
                                lines = Arrays.copyOf(lines, lines.length - 1);
                            } else {
                                lineBuffer.setLength(0);
                            }
                            
                            // 处理完整的行
                            for (String line : lines) {
                                line = line.trim();
                                if (line.isEmpty()) continue;
                                
                                log.info("处理行: {}", line);
                                
                                // 处理SSE格式: data: {...}
                                if (line.startsWith("data:")) {
                                    String data = line.substring(5).trim();
                                    
                                    if ("[DONE]".equals(data)) {
                                        log.info("收到结束标记");
                                        continue;
                                    }
                                    
                                    try {
                                        JSONObject json = JSON.parseObject(data);
                                        JSONArray choices = json.getJSONArray("choices");
                                        if (choices != null && !choices.isEmpty()) {
                                            JSONObject choice = choices.getJSONObject(0);
                                            JSONObject delta = choice.getJSONObject("delta");
                                            if (delta != null) {
                                                String content = delta.getString("content");
                                                if (content != null && !content.isEmpty()) {
                                                    contentCount[0]++;
                                                    log.info("第{}块内容: [{}]", contentCount[0], content);
                                                    onContent.accept(content);
                                                }
                                            }
                                        }
                                    } catch (Exception e) {
                                        log.error("解析JSON失败: data={}, error={}", data, e.getMessage());
                                    }
                                }
                            }
                        } finally {
                            // 释放DataBuffer
                            DataBufferUtils.release(dataBuffer);
                        }
                    })
                    .doOnError(error -> {
                        log.error("流式请求出错: {}", error.getMessage(), error);
                    })
                    .doOnComplete(() -> {
                        log.info("流式请求完成，共收到{}块内容", contentCount[0]);
                    })
                    .blockLast();
            
        } catch (Exception e) {
            log.error("调用智谱AI流式接口失败: {}", e.getMessage(), e);
            throw new RuntimeException("调用AI服务失败: " + e.getMessage(), e);
        }
    }
    
    private ChatSession getOrCreateSession(Long userId, String sessionId) {
        if (StringUtils.hasText(sessionId)) {
            // 查找现有会话
            return sessionRepository.findByIdAndUserId(sessionId, userId)
                    .orElseThrow(() -> new RuntimeException("会话不存在"));
        } else {
            // 创建新会话
            ChatSession session = new ChatSession();
            session.setId(UUID.randomUUID().toString());
            session.setUserId(userId);
            session.setTitle("新对话");
            session.setCreateTime(new Date());
            session.setUpdateTime(new Date());
            session.setMessageCount(0);
            session.setDeleted(false);
            return sessionRepository.save(session);
        }
    }
    
    @Override
    public List<ChatMessage> getSessionMessages(Long userId, String sessionId) {
        return messageRepository.findByUserIdAndSessionIdOrderByCreateTimeAsc(userId, sessionId);
    }
    
    @Override
    @Transactional
    public void clearSession(Long userId, String sessionId) {
        // 验证会话归属
        ChatSession session = sessionRepository.findByIdAndUserId(sessionId, userId)
                .orElseThrow(() -> new RuntimeException("会话不存在"));
        
        // 删除所有消息
        messageRepository.deleteBySessionId(sessionId);
        
        // 标记会话为已删除
        session.setDeleted(true);
        session.setUpdateTime(new Date());
        sessionRepository.save(session);
        
        log.info("会话已清除: userId={}, sessionId={}", userId, sessionId);
    }
    
    @Override
    public List<ChatSession> getUserSessions(Long userId) {
        return sessionRepository.findByUserIdAndDeletedOrderByUpdateTimeDesc(userId, false);
    }
    
    @Override
    public ChatSession createSession(Long userId, String title) {
        ChatSession session = new ChatSession();
        session.setId(UUID.randomUUID().toString());
        session.setUserId(userId);
        session.setTitle(StringUtils.hasText(title) ? title : "新对话");
        session.setCreateTime(new Date());
        session.setUpdateTime(new Date());
        session.setMessageCount(0);
        session.setDeleted(false);
        return sessionRepository.save(session);
    }
}

